﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Configuration;
using KC.DataAccess.MV;
using KC.ExtensionMethods;
using BLL = KC.Business.Web;
using Logger = KC.Logging.Logger;

public partial class site : System.Web.UI.MasterPage
{
	private DateTime started;
	public IP ip;
	public Session session;
	public Dictionary<string, string> values;
	public Activity act;
	protected MV8DataContext dc = new MV8DataContext(ConfigurationManager.ConnectionStrings["MV8"].ConnectionString);

	protected void Page_Init(object sender, EventArgs e)
	{
		try {
			started = DateTime.Now;
			this.Error += new EventHandler(Page_Error);

			DetectIp();
			if (session == null) InitSession();
			LogActivity(null); }
		catch { }
	}
	protected void Page_Error(object sender, EventArgs e)
	{
		try { Logger.LogError(Logger.Project.MV, Logger.ErrorLevel.Critical, "Unhandled exception caught at the top level: \n" + Server.GetLastError().ToString()); }
		catch { }
	}
	protected void Page_Load(object sender, EventArgs e)
    {
		// Detect spammy IPs and block their asses
		string domain = "";
		if (Request.UrlReferrer != null )
			domain = Request.UrlReferrer.GetRootDomain();
		if (!string.IsNullOrEmpty(domain) && Request.UrlReferrer.AbsoluteUri.ToLower().Trim().EndsWith("/sitemap.html")) {
			ip.NumProblems++;
			Response.Write("Your IP has been flagged for possible spam. Referrer: " + Server.HtmlEncode(Request.UrlReferrer.AbsoluteUri.ToLower().Trim()) + "<br />Furthermore, " + Server.HtmlEncode(domain) + " has ben added to the blacklist.");
			var blacklists = from b in dc.Blacklists where b.domain.ToLower() == domain.ToLower() select b;
			if (blacklists.Count() == 0)
				dc.Blacklists.InsertOnSubmit(new Blacklist() { AttemptedUsages = 1, domain = domain });
			else blacklists.First().AttemptedUsages++;
			dc.SubmitChanges(); }

		// Detect and handle spammy TLDs (Because I get SO much legit traffic from .ru referrers)
		if (!string.IsNullOrEmpty(domain) && domain.Trim().ToLower().Replace("/", "").Replace("\\", "").EndsWithAny(new string[] { "ru", "tk" }))
		{
			ip.NumProblems++;
			dc.SubmitChanges();
			var blacklists = from b in dc.Blacklists where b.domain.ToLower() == domain.ToLower() select b;
			if (blacklists.Count() == 0)
				dc.Blacklists.InsertOnSubmit(new Blacklist() { AttemptedUsages = 1, domain = domain });
			else blacklists.First().AttemptedUsages++;
			dc.SubmitChanges();
		}


		// Ban IPs with many problems
		if (ip.NumProblems >= 3) {
			Response.Clear();
			Response.Write("<div style=\"width: 100%; text-align: center; margin: 0 auto;\"><img src=\"images/picard-flip.jpg\" alt=\"fuck you, asshole\" /></div><br /><br />\r\n");
			Response.Write("<h1 style=\"text-align:center;\">Access denied for spam</h1><br /><br /><table style=\"width: 100%;\">\r\n");

			List<KC.DataAccess.MV.Session> sessions = ip.Sessions.OrderByDescending(s => s.ID).Take(500).ToList();
			for (int i = 0; i < 100 && i < ip.Sessions.Count(); i++) {
				foreach (Activity act in sessions[i].Activities.ToList())
					Response.Write("<tr><td>"+act.DateTime.ToString("MM/dd/yy HH:mm:ss")+"</td><td>" + act.Session.IP.Address + "</td><td>" + (act.Referrer ?? "&nbsp;") + "</td><td>" + act.Request + "</td></tr>\r\n"); }
			Response.Write("</table>");
			Controls.Clear();
			Response.Flush();
			Response.End();
			this.Session.Abandon();
			
			return; }

		SelectMenuNode();
		if (session != null)
			session.dEnded = DateTime.Now;

		LogSearchResult();    
	}

	private void SelectMenuNode()
	{
		// Get the current page, the whole page, and nothing but the page.  Just the Fax, ma'am.
		string page = Request.RawUrl.Substring(Request.RawUrl.LastIndexOf('/') + 1);
		if (page.Contains('?')) page = page.Substring(0, page.IndexOf('?'));

		int index = 0;
		switch (page.ToLower()) {
			case "":
			case "default.aspx":
			default:
				index = 0; break;
			case "issues.aspx":
				index = 1; break;
			case "about.aspx":
				index = 2; break;
		}

		// Update styles appropriately
		tMenu.Rows[0].Cells[index].Style.Add("border-bottom", "solid 1px #ffffff");
		tMenu.Rows[0].Cells[index].Style.Add("border-top", "solid 3px #565656;");
	}
	private void DetectIp()
	{
		// Find any IP(s) matching this address
		var ips = from a in dc.IPs
				where a.Address == Request.UserHostAddress
				orderby a.LastAccess descending 
				select a;
		if (ips.Count() == 1) // Exactly one match; use it.
			ip = ips.First();
		else if (ips.Count() > 1) { // Multiple matches; error out and use the most recent one.
			// TODO
			// Logger.Write("MV7","Duplicate IPs", "Multiple IPs detected with Address " + Request.UserHostAddress + "; using " + ips.First().ID.ToString(), Logger.Severity.Error);
			ip = ips.First();
			return; }
		if (ips.Count() == 0) { // No matches; add a new one
			ip = new IP();
			ip.Address = Request.UserHostAddress;
			try { ip.Domain = Request.UserHostName; }
			catch { }
			ip.FirstAccess = DateTime.Now;
			ip.Hits = 0;
			ip.isSpider = KC.Business.Net.Tracking.Spiders.isSpider(Request.UserAgent, Request.UserHostAddress);
			dc.IPs.InsertOnSubmit(ip); }

		// Update IP
		ip.Hits++;
		ip.LastAccess = DateTime.Now;
		dc.SubmitChanges();

	}
	private void InitSession()
	{
		session = new Session();
		session.dStarted = DateTime.Now;
		session.dEnded = DateTime.Now;
		session.IPID = ip.ID;
		session.UID = null;
		dc.Sessions.InsertOnSubmit(session);
		dc.SubmitChanges();
	}
	public void LogActivity(int? PostID)
	{
		try
		{
			dc.SubmitChanges();
			act = new Activity();
			act.SID = session.ID;
			act.DateTime = DateTime.Now;
			if (PostID != null) act.PID = PostID;
			dc.Activities.InsertOnSubmit(act);
			act.Request = Request.RawUrl;
			act.Referrer = Request.UrlReferrer == null ? null : Request.UrlReferrer.AbsoluteUri;
			dc.SubmitChanges();
		}
		catch { }

	}
	private void LogSearchResult()
	{
		// Detect whether this is a search engine referrer
		if (Request.UrlReferrer == null || string.IsNullOrEmpty(Request.UrlReferrer.AbsoluteUri)) return;
		string 
			engine = null,
			query = null;
		if (!BLL.RequestTools.isSearchEngineReferral(Request.UrlReferrer, out engine, out query)) return;

		Console.Beep(2500, 100);
		SearchResult sr = new SearchResult();
		sr.Query = query;
		sr.Engine = engine;
		sr.FullURL = Request.UrlReferrer.AbsoluteUri;
		sr.BaseURL = Request.UrlReferrer.GetRootDomain();
		sr.datetime = DateTime.Now;
		sr.AID = act.ID;
		dc.SearchResults.InsertOnSubmit(sr);
		dc.SubmitChanges();
	}

}
